package service

import (
	"context"
	"fmt"
	"os"
	"path"
	"strconv"
	"time"

	"gitee.com/k-ayaka/et-userserver/api"
	"gitee.com/k-ayaka/et-userserver/config"
	"gitee.com/k-ayaka/et-userserver/dao"
	"gitee.com/k-ayaka/et-userserver/util"
	"gitee.com/k-ayaka/std-go/crypto"
	"gitee.com/k-ayaka/std-go/redis"
)

const ACTIVATE_AES_KEY = "Bt3vOe2ljkletq3V"

type UserService struct{}

func (u *UserService) SignUp(ctx context.Context, req *api.SignUpReq) (*api.SignUpResp, error) {
	// register an inactive account
	user := dao.CreateUser(req.Name, crypto.Md5EncryptToHexUpper(req.Password), req.Email, int(req.Tel))
	token := util.GenerateToken(int(user.ID))
	go util.CacheToken(token, int(user.ID))
	go util.CacheUserInfo(user)
	return &api.SignUpResp{Success: true, Message: "注册成功", Token: token}, nil
}

func (u *UserService) SignIn(ctx context.Context, req *api.SignInReq) (*api.SignInResp, error) {
	// verify ID
	user := dao.SelectUser(int(req.Id))
	if user == nil {
		return &api.SignInResp{Success: false, Message: "用户ID不存在"}, nil
	}
	// match Password
	if !util.MatchPassword(req.Password, user) {
		return &api.SignInResp{Success: false, Message: "密码错误"}, nil
	}
	token := util.GenerateToken(int(user.ID))
	go util.CacheToken(token, int(user.ID))
	go util.CacheUserInfo(user)
	return &api.SignInResp{Success: true, Message: "登录成功", Token: token}, nil
}

func (u *UserService) SignOut(ctx context.Context, req *api.SignOutReq) (*api.GenericResp, error) {
	id := util.Token2UID(req.Token)
	if id == -1 {
		return &api.GenericResp{Success: false, Message: "登录Token已失效"}, nil
	}
	go redis.DelByKey(req.Token)
	go redis.DelByKey(strconv.Itoa(id))
	return &api.GenericResp{Success: true, Message: "操作成功"}, nil
}

func (u *UserService) GetUserInfo(ctx context.Context, req *api.GetUserInfoReq) (*api.GetUserInfoResp, error) {
	id := util.Token2UID(req.Token)
	if id == -1 {
		return &api.GetUserInfoResp{Success: false, Message: "登录Token已失效"}, nil
	}
	user := util.GetUserInfo(id)
	if user == nil {
		// access database
		user = dao.SelectUser(id)
		go util.CacheUserInfo(user)
	}
	return &api.GetUserInfoResp{Success: true, Message: "操作成功", User: &api.User{
		Id:      int32(user.ID),
		Name:    user.Name,
		Profile: user.Profile,
		Email:   user.Email,
		Tel:     int32(user.Tel),
	}}, nil
}

func (u *UserService) UploadProfile(ctx context.Context, req *api.UploadProfileReq) (*api.UploadProfileResp, error) {
	id := util.Token2UID(req.Token)
	if id == -1 {
		return &api.UploadProfileResp{Success: false, Message: "登录Token已失效"}, nil
	}
	profile := fmt.Sprintf("%d_%d.jpg", id, time.Now().Unix())
	file, _ := os.Create(path.Join(config.PROFILE_PERSIST_URL, profile))
	file.Write(req.File)
	err := file.Close()
	if err != nil {
		return &api.UploadProfileResp{Success: false, Message: "头像文件上传失败"}, nil
	}
	return &api.UploadProfileResp{Success: true, Message: "更新成功", Profile: profile}, nil
}

func (u *UserService) UpdateProfile(ctx context.Context, req *api.UpdateProfileReq) (*api.GenericResp, error) {
	id := util.Token2UID(req.Token)
	if id == -1 {
		return &api.GenericResp{Success: false, Message: "登录Token已失效"}, nil
	}
	user := util.GetUserInfo(id)
	if user == nil {
		// access database
		user = dao.SelectUser(id)
	}
	user.Profile = req.Profile
	if !dao.UpdateUser(user) {
		return &api.GenericResp{Success: false, Message: "更新失败，数据库连接超时"}, nil
	}
	go util.CacheUserInfo(user)
	return &api.GenericResp{Success: true, Message: "更新成功"}, nil
}

func (u *UserService) UpdateUserInfo(ctx context.Context, req *api.UpdateUserInfoReq) (*api.GenericResp, error) {
	id := util.Token2UID(req.Token)
	if id == -1 {
		return &api.GenericResp{Success: false, Message: "登录Token已失效"}, nil
	}
	user := util.GetUserInfo(id)
	if user == nil {
		// access database
		user = dao.SelectUser(id)
	}
	user.Name = req.Name
	user.Email = req.Email
	user.Tel = int(req.Tel)
	if !dao.UpdateUser(user) {
		return &api.GenericResp{Success: false, Message: "更新失败, 数据库连接超时"}, nil
	}
	go util.CacheUserInfo(user)
	return &api.GenericResp{Success: true, Message: "更新成功"}, nil
}

func (u *UserService) UpdatePassword(ctx context.Context, req *api.UpdatePasswordReq) (*api.GenericResp, error) {
	id := util.Token2UID(req.Token)
	if id == -1 {
		return &api.GenericResp{Success: false, Message: "登录Token已失效"}, nil
	}
	user := util.GetUserInfo(id)
	if user == nil {
		// access database
		user = dao.SelectUser(id)
	}
	if !util.MatchPassword(req.Password, user) {
		return &api.GenericResp{Success: false, Message: "密码错误"}, nil
	}
	user.Password = req.NewPassword
	if !dao.UpdateUser(user) {
		return &api.GenericResp{Success: false, Message: "更新失败, 数据库连接超时"}, nil
	}
	go util.CacheUserInfo(user)
	return &api.GenericResp{Success: true, Message: "更新成功"}, nil
}
